﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;
using System8Equations;
using System.Linq;

namespace t_System8Equations
{
    /// <summary>
    /// Test the series accumulator
    /// </summary>
    [TestClass]
    public class t_EqnSeriesAccumulator
    {
        [TestMethod]
        public void TestCTor()
        {
            EqnSeriesAccumulator eqn = new EqnSeriesAccumulator();
        }

        [TestMethod]
        public void TestNoVariations()
        {
            EqnSeriesAccumulator eqn = new EqnSeriesAccumulator();
            System8Equations.S8Equations S8 = new System8Equations.S8Equations();
            SetupS8StartingValues(S8);

            var refBottom = eqn.Watch(() => S8.n.Bottom);

            eqn.Loop(10);
            double[] values = eqn.GetValueList(refBottom);

            Assert.AreEqual(10, values.Length, "Should have gotten back 10 values... weird");
            Assert.AreEqual(0, values.FirstOrDefault(v => v != 10000), "Expected to see only the number 10000");
        }

        /// <summary>
        /// Helper class that returns a simple integer in progression... Probably somethign called "range" that will do this!
        /// </summary>
        class IntegerStep : IEnumerator<double>
        {
            int _current;
            public IntegerStep(int initialValue)
            {
                _current = initialValue;
            }

            public double Current
            {
                get { return _current; }
            }

            public void Dispose()
            {
            }

            object System.Collections.IEnumerator.Current
            {
                get { return _current; }
            }

            public bool MoveNext()
            {
                _current++;
                return true;
            }

            public void Reset()
            {
                _current = 0;
            }
        }

        [TestMethod]
        public void TestSimpleStep()
        {
            EqnSeriesAccumulator eqn = new EqnSeriesAccumulator();
            System8Equations.S8Equations S8 = new System8Equations.S8Equations();
            SetupS8StartingValues(S8);

            var refBottom = eqn.Watch(() => S8.n.Bottom);
            var refBottomn1 = eqn.Watch(() => S8.n1.Bottom);
            IntegerStep si = new IntegerStep(10000);
            eqn.SetOnIteration(() => { S8.n.Bottom = si.Current; si.MoveNext(); });

            eqn.Loop(10);
            double[] values = eqn.GetValueList(refBottom);
            double[] n1values = eqn.GetValueList(refBottomn1);

            Assert.AreEqual(10, values.Length, "Should have gotten back 10 values... weird");
            for (int i = 0; i < 10; i++)
            {
                Assert.AreEqual(10000 + i, values[i], "Value didn't inc the way we were expecting");
                Assert.AreEqual((10000.0 + i) / 2.0, n1values[i], "The n1 values aren't moving at half the rate either.");
            }
        }

        /// <summary>
        /// Sets up a good default set of numbers to start with.
        /// </summary>
        /// <param name="eqn"></param>
        private void SetupS8StartingValues(System8Equations.S8Equations eqn)
        {
            eqn.n.Bottom = 10000;
            eqn.n.Charm = 10000;
            eqn.n.Light = 10000;

            eqn.n1.Bottom = 5000;
            eqn.n1.Charm = 5000;
            eqn.n1.Light = 5000;

            eqn.n2.Bottom = 5000;
            eqn.n2.Charm = 5000;
            eqn.n2.Light = 5000;

            eqn.n12.Bottom = 2500;
            eqn.n12.Charm = 2500;
            eqn.n12.Light = 2500;

            eqn.p.Bottom = 10000;
            eqn.p.Charm = 10000;
            eqn.p.Light = 10000;

            eqn.p1.Bottom = 5000;
            eqn.p1.Charm = 5000;
            eqn.p1.Light = 5000;

            eqn.p2.Bottom = 5000;
            eqn.p2.Charm = 5000;
            eqn.p2.Light = 5000;

            eqn.p12.Bottom = 2500;
            eqn.p12.Charm = 2500;
            eqn.p12.Light = 2500;
        }
    }
}